#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>

#include "iot_gpio_ex.h"
#include "ohos_init.h"
#include "cmsis_os2.h"

#include "iot_gpio.h"
#include "iot_errno.h"
#include "iot_pwm.h"
#include "iot_i2c.h"
#include "iot_adc.h"

#include "hi_time.h"
#include "hi_io.h"
#include "hi_errno.h"
#include "hi_adc.h"

#include "pca9555.h"
#include "ssd1306_fonts.h"
#include "oled_ssd1306.h"
#include "iot_watchdog.h"

#define STACK_SIZE 2048

// === I2C + OLED 配置 ===
#define OLED_SDA IOT_IO_NAME_GPIO_13
#define OLED_SCL IOT_IO_NAME_GPIO_14
#define OLED_SDA_FUNC IOT_IO_FUNC_GPIO_13_I2C0_SDA
#define OLED_SCL_FUNC IOT_IO_FUNC_GPIO_14_I2C0_SCL
#define OLED_I2C_IDX 0

// === DHT11 温湿度传感器 ===
#define DHT11_PIN IOT_IO_NAME_GPIO_7
#define DHT11_MAX_RETRY 5
#define DHT11_DATA_BITS 40
static float temperature = 0.0;
static float humidity = 0.0;
osMutexId_t dht11_mutex;

// === MQ7 模拟气体检测 ===
#define MQ7_ADC_CHANNEL IOT_ADC_CHANNEL_5
#define MQ7_AO_PIN IOT_IO_NAME_GPIO_11
#define MQ7_DO_PIN IOT_IO_NAME_GPIO_10
#define DANGER_THRESHOLD 200
static uint32_t gas_value = 0;

// === 蜂鸣器 ===
#define BUZZER_PIN IOT_IO_NAME_GPIO_12
#define BUZZER_FUNC IOT_IO_FUNC_GPIO_12_PWM3_OUT
#define BUZZER_PWM_PORT 3
#define TEMP_THRESHOLD 30

// === 初始化函数 ===
void Buzzer_Init() {
    IoTGpioInit(BUZZER_PIN);
    IoSetFunc(BUZZER_PIN, BUZZER_FUNC);
    IoTPwmInit(BUZZER_PWM_PORT);
    IoTPwmStop(BUZZER_PWM_PORT);
}

void Buzzer_On()  { IoTPwmStart(BUZZER_PWM_PORT, 50, 3000); }
void Buzzer_Off() { IoTPwmStop(BUZZER_PWM_PORT); }

void OLED_Init() {
    IoSetFunc(OLED_SDA, OLED_SDA_FUNC);
    IoSetFunc(OLED_SCL, OLED_SCL_FUNC);
    IoTI2cInit(OLED_I2C_IDX, 400000);
    usleep(50000);
    OledInit();
    OledFillScreen(0x00);
}

// === DHT11读取 ===
void dht11_delay_us(uint32_t us) {
    uint32_t start = hi_get_us();
    while ((hi_get_us() - start) < us);
}

int DHT11_Read(void) {
    uint8_t data[5] = {0};
    uint8_t state;
    uint32_t timings[DHT11_DATA_BITS * 2] = {0};

    IoTGpioSetDir(DHT11_PIN, IOT_GPIO_DIR_OUT);
    IoTGpioSetOutputVal(DHT11_PIN, IOT_GPIO_VALUE0);
    dht11_delay_us(18000);
    IoTGpioSetOutputVal(DHT11_PIN, IOT_GPIO_VALUE1);
    dht11_delay_us(40);
    IoTGpioSetDir(DHT11_PIN, IOT_GPIO_DIR_IN);

    for (int phase = 0; phase < 3; ++phase) {
        for (int timeout = 1000; timeout > 0; --timeout) {
            if (IoTGpioGetInputVal(DHT11_PIN, &state) != 0) return -1;
            if ((phase % 2 == 0 && state == 0) || (phase % 2 == 1 && state == 1)) break;
            dht11_delay_us(1);
        }
    }

    uint32_t start_time = hi_get_us();
    for (int i = 0; i < DHT11_DATA_BITS * 2; i++) {
        uint8_t last = state;
        int timeout = 1000;
        while (state == last && timeout--) {
            if (IoTGpioGetInputVal(DHT11_PIN, &state) != 0) return -1;
            dht11_delay_us(1);
        }
        timings[i] = hi_get_us() - start_time;
        start_time = hi_get_us();
    }

    for (int i = 0; i < DHT11_DATA_BITS; i++) {
        uint32_t high = timings[i * 2 + 1];
        if (high > 40)
            data[i / 8] |= (1 << (7 - (i % 8)));
    }

    if (data[4] == (data[0] + data[1] + data[2] + data[3])) {
        osMutexAcquire(dht11_mutex, osWaitForever);
        humidity = data[0];
        temperature = data[2];
        osMutexRelease(dht11_mutex);
        return 0;
    }
    return -1;
}

// === MQ7采集 ===
void MQ7_Init() {
    IoTGpioInit(MQ7_AO_PIN);
    IoSetFunc(MQ7_AO_PIN, IOT_IO_FUNC_GPIO_11_GPIO);
    IoTGpioSetDir(MQ7_AO_PIN, IOT_GPIO_DIR_IN);

    IoTGpioInit(MQ7_DO_PIN);
    IoSetFunc(MQ7_DO_PIN, IOT_IO_FUNC_GPIO_10_GPIO);
    IoTGpioSetDir(MQ7_DO_PIN, IOT_GPIO_DIR_IN);
}

void GetMQ7Data() {
    unsigned short data = 0;
    IotGpioValue do_val;
    AdcRead(MQ7_ADC_CHANNEL, &data, IOT_ADC_EQU_MODEL_4, IOT_ADC_CUR_BAIS_DEFAULT, 0xff);
    IoTGpioGetInputVal(MQ7_DO_PIN, &do_val);
    gas_value = data;

    // 保留 MQ7 报警条件
    if (data > DANGER_THRESHOLD || do_val == IOT_GPIO_VALUE1) {
        Buzzer_On();
    }
}

// === 线程 ===
void DHT11Task(void *arg) {
    while (1) {
        if (DHT11_Read() == 0) {
            float temp, hum;
            osMutexAcquire(dht11_mutex, osWaitForever);
            temp = temperature;
            hum = humidity;
            osMutexRelease(dht11_mutex);

            //DHT11 报警逻辑
            if (temp >= 30.0 || hum >= 75.0) {
                Buzzer_On();
            } else {
                Buzzer_Off();
            }
        }
        osDelay(200);
    }
}

void MQ7Task(void *arg) {
    MQ7_Init();
    while (1) {
        GetMQ7Data();
        osDelay(200);
    }
}

void OLEDTask(void *arg) {
    char buf[32];
    float t, h;
    OLED_Init();
    while (1) {
        osMutexAcquire(dht11_mutex, osWaitForever);
        t = temperature;
        h = humidity;
        osMutexRelease(dht11_mutex);

        OledFillScreen(0);
        snprintf(buf, sizeof(buf), "Temp: %.1fC", t);
        OledShowString(0, 0, buf, 1);
        snprintf(buf, sizeof(buf), "Humi: %.1f%%", h);
        OledShowString(0, 2, buf, 1);
        snprintf(buf, sizeof(buf), "Gas: %lu %s", gas_value, gas_value > DANGER_THRESHOLD ? "DANGER" : "SAFE");
        OledShowString(0, 4, buf, 1);
        osDelay(200);
    }
}

void AppMain(void) {
    dht11_mutex = osMutexNew(NULL);
    Buzzer_Init();
    OLED_Init();

    osThreadAttr_t attr = {
        .stack_size = STACK_SIZE,
        .priority = osPriorityNormal,
    };
    attr.name = "DHT11Task";
    osThreadNew(DHT11Task, NULL, &attr);

    attr.name = "MQ7Task";
    osThreadNew(MQ7Task, NULL, &attr);

    attr.name = "OLEDTask";
    osThreadNew(OLEDTask, NULL, &attr);
}

APP_FEATURE_INIT(AppMain);
